package marcis.jarina.directory.sourcedir;

import marcis.jarina.directory.FileActionListener;
import org.apache.log4j.Logger;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author jan.marcis
 */
public class SourceProcessor implements SourceService, FileActionListener {

    private static final Logger log = Logger.getLogger("marcis.jarina.SourceProcessor");

    private final List<String> importAccumulator = new ArrayList<String>();

    private File sourceFolder = new File("src/main/java");

    public File getSourceFolder() {
        return sourceFolder;
    }

    public void setSourceFolder(File sourceFolder) {
        this.sourceFolder = sourceFolder;
    }

    @Override
    public Collection<String> extractImportsFromCode(String code) {
        String[] splitted = code.split(System.getProperty("line.separator"));
        if (splitted.length == 1) {
            splitted = code.split("\n");
        }
        Pattern pat = Pattern.compile("import .*?;");
        Collection<String> result = new TreeSet<String>();
        for (String line : splitted) {
            Matcher mat = pat.matcher(line);
            if (mat.find()) {
                String res = mat.group(0);
                // without 'import ' and without ';'
                res = res.substring(7, res.length() - 1);
                if (!isJREImport(res)) {
                    result.add(res);
                }
            }
        }
        return result;
    }

    private boolean isJREImport(String imp) {
        final List<String> JRE_PREFIXES = Arrays.asList("java.util.",
                "javax.persistence", "java.lang.", "java.io.");
        for (String prefix : JRE_PREFIXES) {
            if (imp.contains(prefix)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String getSourceCode(File javaFile) {
        log.debug("Getting source code for: " + javaFile.getName());
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(javaFile));
            char[] cbuf = new char[1024];
            StringBuilder sb = new StringBuilder();
            int size;
            while ((size = br.read(cbuf)) != -1) {
                char[] reallyReaded = new char[size];
                // TODO proper array copy
                System.arraycopy(cbuf, 0, reallyReaded, 0, size);
                String addStr = new String(reallyReaded);
                sb.append(addStr);
            }
            return sb.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }


    @Override
    public void onFileFound(File file) {
        importAccumulator.addAll(extractImportsFromCode(getSourceCode(file)));
    }

    @Override
    public File getRepositoryDir() {
        throw new IllegalStateException("Why to ask source processor at repository?");
    }

    @Override
    public void finish() {
        //nothing?
    }

    public List<String> getImportAccumulator() {
        return importAccumulator;
    }

}
